import csv
import json
import os
import yaml
from pathlib import Path


def load_config(yaml_path: str) -> dict:
    """加载YAML配置文件"""
    with open(yaml_path, 'r', encoding='utf-8') as f:
        return yaml.safe_load(f)


def map_csv_to_headers(row: dict) -> dict:
    """提取CSV中以header_开头的动态请求头"""
    headers = {}
    for key, value in row.items():
        if key.startswith('header_'):
            header_name = key.replace('header_', '', 1)
            headers[header_name] = value
    return headers

def load_csv_data(csv_path: str) -> list:
    """加载并预处理CSV数据"""
    project_root = Path(__file__).parent.parent
    csv_abs_path = project_root / csv_path

    if not csv_abs_path.exists():
        raise FileNotFoundError(f"CSV文件不存在：{csv_abs_path}")

    with open(csv_abs_path, 'r', encoding='ANSI') as f:
        reader = csv.DictReader(f, quoting=csv.QUOTE_ALL)  # 自动处理引号
        cases = []
        for row in reader:
            try:
                # 关键：解析 JSON 并验证类型
                raw_body = row['request_body']
                parsed_body = json.loads(raw_body)
                if not isinstance(parsed_body, dict):
                    raise ValueError(f"JSON 解析结果非字典类型: {type(parsed_body)}")
                row['request_body'] = parsed_body
            except KeyError:
                raise KeyError(f"CSV 缺少必要字段 'request_body'")
            except json.JSONDecodeError as e:
                raise ValueError(f"行 {reader.line_num} JSON 语法错误: {e}")
            except Exception as e:
                raise RuntimeError(f"数据处理失败: {str(e)}")
            cases.append(row)
        return cases



def get_test_cases(config_path: str = os.path.abspath(os.path.join(os.getcwd(),))+"\\testcases\\multi_api_config.yml") -> list:
    """生成多接口测试用例"""
    config = load_config(config_path)
    test_cases = []

    for api_config in config['apis']:
        csv_data = load_csv_data(api_config['csv_file'])

        for row in csv_data:
            # 合并请求头
            merged_headers = api_config.get('fixed_headers', {}).copy()
            for key in list(row.keys()):
                if key.startswith('header_'):
                    header_name = key.replace('header_', '', 1)
                    merged_headers[header_name] = row.pop(key)

            # 获取请求数据（直接使用已解析的字典）
            request_data = row.get(api_config['params_mapping']['request_body'], {})

            # 构建测试用例
            test_case = {
                "case_id": row[api_config['params_mapping']['case_id']], # 用例标识
                "description": row[api_config['params_mapping']['description']],
                "api_name": api_config['name'],# 接口标识
                "endpoint": api_config['endpoint'],  # 接口地址
                "url": f"{config['base_url']}{api_config['endpoint']}",# 接口完整地址
                "method": api_config['method'].upper(),# 请求方法
                "headers": merged_headers,# 请求头
                "data": request_data,# 请求参数
                "expected": {
                    "status_code": int(row[api_config['expected']['status_code']]),
                    "body_code": int(row[api_config['expected']['body_code']]),
                    "msg": row.get(api_config['expected']['msg'], "")
                }
            }
            test_cases.append(test_case)

    return test_cases

            # test_case = {
            #     "case_id": row[api_config['params_mapping']['case_id']],  # 用例标识
            #     "api_name": api_config['name'],  # 接口标识
            #     "endpoint": api_config['endpoint'],  # 接口地址
            #     "url": config['base_url'] + api_config['endpoint'],  # 接口完整地址
            #     "method": api_config['method'],  # 请求方法
            #     "headers": merged_headers,  # 请求头
            #     "data": request_data,  # 请求参数
            #     "expected": {
            #         "status_code": int(row[api_config['expected']['status_code']]),
            #         # 扩展字段
            #         "msg": row.get(api_config['expected'].get('response_msg', ''), '')
            #     }  # 预期结果
            # }
            # test_cases.append(test_case)

            # 自动映射带前缀的参数
            # auto_params = {
            #     key.replace(
            #         api_config.get('param_prefix', 'param_'),  # 要替换的前缀
            #         '',  # 替换为的空字符串
            #         1  # 仅替换一次（可选）
            #     ): value
            #     for key, value in row.items()
            #     if key.startswith(api_config.get('param_prefix', 'param_'))
            # }
            # 合并手动配置参数（优先级高）
            # manual_params = {
            #     key: row[col]
            #     for key, col in api_config.get('params_mapping', {}).items()
            #     if key != 'case_id'
            # }



    return test_cases